package com.example.test.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;

//图片点选验证码
public class ImageClickCaptchaGenerator {

    private static final Logger logger = LoggerFactory.getLogger(ImageClickCaptchaGenerator.class);

    // 底图存放的文件夹路径
    private static final String BASE_IMAGE_DIR = "D:\\java_project\\baseImages";
    // 小图存放的文件夹路径
    private static final String TARGET_IMAGE_DIR = "D:\\java_project\\targetImages";

    private static List<Point> correctClickPoints = new ArrayList<>();

    private static List<String> targetImages = new ArrayList<>();

    private static List<String> picNames = new ArrayList<>();

    public static BufferedImage generateCaptchaImage() throws Exception {
        // 随机获取一张底图
        File baseImageFile = getRandomBaseImage();
        BufferedImage baseImage = ImageIO.read(baseImageFile);

        //创建一个 Graphics2D 对象( 2D 图形绘制)
        Graphics2D g2d = baseImage.createGraphics();

        // 目标小图数量
        int targetCount = 4;

        int successNum = 0;

        int errorNum = 0;

        while (true) {
            if (errorNum >= 100 || successNum >= targetCount) break;
            // 随机获取一张小图
            File targetImageFile = getRandomTargetImage();
            if (!picNames.contains(targetImageFile.getName())) {
                picNames.add(targetImageFile.getName());
                BufferedImage targetImage = ImageIO.read(targetImageFile);
                targetImages.add(fileToBase64(targetImageFile));
                // 随机计算目标小图在底图上的放置位置（确保不超出底图范围）
                int x = new Random().nextInt(baseImage.getWidth() - targetImage.getWidth());
                int y = new Random().nextInt(baseImage.getHeight() - targetImage.getHeight());
                correctClickPoints.add(new Point(x, y));
                //把小图绘制在目标图形上的x坐标和y坐标上,图像已经完全加载可以直接使用null作为observer
                g2d.drawImage(targetImage, x, y, null);
                successNum++;
            } else {
                errorNum++;
            }
        }
        // 释放资源
        g2d.dispose();
        return baseImage;
    }

    //随机获取底图
    private static File getRandomBaseImage() {
        File baseImageDir = new File(BASE_IMAGE_DIR);
        //返回一个包含目录中文件的数组
        File[] baseImages = baseImageDir.listFiles((dir, name) -> name.endsWith(".jpg"));
        int randomIndex = new Random().nextInt(baseImages.length);
        return baseImages[randomIndex];
    }

    //随机获取小图
    private static File getRandomTargetImage() {
        File targetImageDir = new File(TARGET_IMAGE_DIR);
        File[] targetImages = targetImageDir.listFiles((dir, name) -> name.endsWith(".png"));
        int randomIndex = new Random().nextInt(targetImages.length);
        return targetImages[randomIndex];
    }

    public static List<Point> getCorrectClickPoints() {
        return correctClickPoints;
    }

    public static List<String> getTargetImages() {
        return targetImages;
    }


    public static void destroyed() {
        correctClickPoints.clear();
        targetImages.clear();
        picNames.clear();
    }

    public static boolean isAreaMatch(List<Point> systemPoints, List<Point> userClickPoints, int errorRadius) {
        boolean res = true;
        for (int k = 0; k < systemPoints.size(); k++) {
            Point sysPoint = systemPoints.get(k);
            Point userClickPoint = userClickPoints.get(k);
            if (Math.abs(userClickPoint.x - sysPoint.x) > errorRadius || Math.abs(userClickPoint.y - sysPoint.y) > errorRadius)
                res = false;
        }
        return res;
    }

    public static String fileToBase64(File file) throws IOException {
        try {
            byte[] fileBytes;
            FileInputStream fis = new FileInputStream(file);
            fileBytes = new byte[(int) file.length()];
            fis.read(fileBytes);
            String base64String = "data:image/png;base64," + Base64.getEncoder().encodeToString(fileBytes);
            return base64String;
        } catch (IOException e) {
            logger.error("图片文件转base64字符串失败");
            return null;
        }
    }
}